﻿using System;
using System.IO;

namespace NET.HLW5a.Snippets.Streams
{
    /// <summary>
    /// Several methods for copying one stream onto another
    /// Performance of each method depends on stream length and number of calls
    /// </summary>
    public static class Copy
    {
        /// <summary>
        /// Stream copy using <see cref="System.IO.Stream.ReadByte()"/> and <see cref="System.IO.Stream.WriteByte()"/> in a for-loop
        /// </summary>
        /// <param name="src"></param>
        /// <param name="dst"></param>
        public static void Copy1(Stream src, Stream dst)
        {
            src.Seek(0L, SeekOrigin.Begin);

            for (Int32 b = src.ReadByte(); b != -1; b = src.ReadByte()) dst.WriteByte((Byte)b);

            src.Seek(0L, SeekOrigin.Begin);
            dst.Seek(0L, SeekOrigin.Begin);
        }

        /// <summary>
        /// Stream copy using a <see cref="System.Byte"/> array as buffer and <see cref="System.IO.Stream.Read(System.Byte[], System.Int32, System.Int32)"/> and <see cref="System.IO.Stream.Write(System.Byte[], System.Int32, System.Int32)"/> in a for-loop
        /// </summary>
        /// <param name="src"></param>
        /// <param name="dst"></param>
        public static void Copy2(Stream src, Stream dst)
        {
            src.Seek(0L, SeekOrigin.Begin);

            Byte[] buf = new Byte[2 << 16];
            for (Int32 r = src.Read(buf, 0, buf.Length); r > 0; r = src.Read(buf, 0, buf.Length)) dst.Write(buf, 0, r);

            src.Seek(0L, SeekOrigin.Begin);
            dst.Seek(0L, SeekOrigin.Begin);
        }

        /// <summary>
        /// Stream copy using <see cref="System.IO.Stream.ReadByte()"/> and <see cref="System.IO.Stream.WriteByte()"/> in a while-loop
        /// </summary>
        /// <param name="src"></param>
        /// <param name="dst"></param>
        public static void Copy3(Stream src, Stream dst)
        {
            src.Seek(0L, SeekOrigin.Begin);

            Int32 b;
            while ((b = src.ReadByte()) != -1) dst.WriteByte((Byte)b);

            src.Seek(0L, SeekOrigin.Begin);
            dst.Seek(0L, SeekOrigin.Begin);
        }

        /// <summary>
        /// Stream copy using a <see cref="System.Byte"/> array as buffer and <see cref="System.IO.Stream.Read(System.Byte[], System.Int32, System.Int32)"/> and <see cref="System.IO.Stream.Write(System.Byte[], System.Int32, System.Int32)"/> in a while-loop
        /// </summary>
        /// <param name="src"></param>
        /// <param name="dst"></param>
        public static void Copy4(Stream src, Stream dst)
        {
            src.Seek(0L, SeekOrigin.Begin);

            Int32 r;
            Byte[] buf = new Byte[2 << 16];
            while ((r = src.Read(buf, 0, buf.Length)) > 0) dst.Write(buf, 0, r);

            src.Seek(0L, SeekOrigin.Begin);
            dst.Seek(0L, SeekOrigin.Begin);
        }
    }
}
